/*
* Copyright 2010 Dovado FZ-LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#import "HomeAutomationViewController.h"
#import "DovadoAppDelegate.h"
#import "OnOffTableViewCell.h"
#import "DimmerTableViewCell.h"
#import "Alias.h"
#import "Group.h"
#import "Info.h"
#import "DialogUtils.h"
#import <AudioToolbox/AudioToolbox.h>

@implementation HomeAutomationViewController
@synthesize mTableView;
@synthesize mNetworkRequest;
@synthesize mOnOffAliasArray;
@synthesize mDimmerAliasArray;
@synthesize mGroupAliasArray;
@synthesize latestTimeMark;


typedef enum {
	BUTTON_GROUP_ONOFF = 0,
	BUTTON_GROUP_GROUPS,
	BUTTON_GROUP_DIMMERS,
	BUTTON_GROUP_COUNT
} ButtonGroups_t;


/*
 * Loads the aliases from the router. Usually called in a repsonse to a refresh-call.
 */
- (void) loadAliases {
	if (mNetworkRequest != NULL) {
		request_error_codes_t errorCode = [mNetworkRequest requestGroupsAndAliases];
		if (errorCode == REQUEST_OK) {
			mProgressAlert = [DialogUtils createProgressionAlertWithTitle:NSLocalizedString(@"synching_aliases_alert_title", @"Please wait") 
															   andMessage: NSLocalizedString(@"synching_aliases_alert_message", @"Downloading available aliases")];
		} else {
			[DialogUtils showConnectionFailedDialog:errorCode];
		}
	} else {
		NSLog(@"mNetworkRequest is NULL");
	}
}

/*
 * Sends a 'Turn on' signal to the router for an alias.
 * @param Alias the alias to turn on.
 */
- (void) turnOn:(NSString*) alias {	
	request_error_codes_t errorCode = [mNetworkRequest requestTurnOn: alias];
	if (errorCode == REQUEST_OK) {
		NSString* message = [NSString stringWithFormat:NSLocalizedString(@"turning_on_dialog_message", @"Activating alias %@") , alias];
		mProgressAlert = [DialogUtils createProgressionAlertWithTitle: NSLocalizedString(@"turning_on_off_dialog_title", @"Please wait")  andMessage: message];
	} else {
		[DialogUtils showConnectionFailedDialog:errorCode];
	}
}

/*
 * Sends a 'Turn off' signal to the router for an alias.
 * @param Alias the alias to turn off.
 */
- (void) turnOff:(NSString*) alias {	
	request_error_codes_t errorCode = [mNetworkRequest requestTurnOff: alias];
	if (errorCode == REQUEST_OK) {
		NSString* message = [NSString stringWithFormat:NSLocalizedString(@"turning_off_dialog_message", @"Dectivating alias %@"), alias];
		mProgressAlert = [DialogUtils createProgressionAlertWithTitle: NSLocalizedString(@"turning_on_off_dialog_title", @"Please wait") andMessage: message];	
	} else {
		[DialogUtils showConnectionFailedDialog:errorCode];
	}	
}

/*
 * Sends a dim signal to the router.
 * @param Alias The alias to dim
 * @param The new dimmer value (range between 0 and 100, percent basically...)
 */
- (void) dim:(NSString*) alias value: (NSInteger) dimPercent {	
	request_error_codes_t errorCode = [mNetworkRequest requestDimAlias: alias :dimPercent];
	if (errorCode == REQUEST_OK) {
		NSString* message = [NSString stringWithFormat:NSLocalizedString(@"dimming_dialog_message", @"Dimmar alias %@"), alias];
		mProgressAlert = [DialogUtils createProgressionAlertWithTitle: NSLocalizedString(@"dimming_dialog_title", @"Please wait") andMessage: message];	
	} else {
		[DialogUtils showConnectionFailedDialog:errorCode];
	}
}

- (IBAction) onRefreshButtonClicked {
	NSLog(@"HomeAutomation : onRefreshButtonClicked");
    [self loadAliases];	
}

- (IBAction) onLoginButtonClicked {
	DovadoAppDelegate *appDelegate = (DovadoAppDelegate*) [[UIApplication sharedApplication] delegate];
	[appDelegate.window addSubview:appDelegate.mLoginViewController.view];
    [appDelegate.window makeKeyAndVisible];
}


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {	
	return BUTTON_GROUP_COUNT;    
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	NSInteger retVal = 0;
	switch (section) {
		case BUTTON_GROUP_ONOFF:
			retVal = [mOnOffAliasArray count];
			break;
		case BUTTON_GROUP_GROUPS:
			retVal = [mGroupAliasArray count];
			break;
		case BUTTON_GROUP_DIMMERS:
			retVal = [mDimmerAliasArray count];
			break;
			
		default:
			NSLog(@"Error - tried to access non-existant group!");
			retVal = 0;
			break;
	}
	
    return retVal;
}

-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; {	
	NSString* retVal = NULL;
	switch (section) {
		case BUTTON_GROUP_ONOFF:
			if ([mOnOffAliasArray count]>0) {
				retVal = NSLocalizedString(@"header_on_off_buttons", @"On/Off Buttons");
			}
			break;
		case BUTTON_GROUP_GROUPS:
			if ([mGroupAliasArray count]>0) {
				retVal = NSLocalizedString(@"header_group_buttons", @"Group Buttons");
			} 
			break;
		case BUTTON_GROUP_DIMMERS:
			if ([mDimmerAliasArray count]>0) {
				retVal = NSLocalizedString(@"header_dimmer_buttons", @"Dimmer Buttons");
			}
			break;
			
		default:
			NSLog(@"Error - tried to access non-existant group!");
			retVal = 0;
			break;
	}
	return retVal;
}

/*
 * Loads an OnOffTableCell from a nib-file.
 */
- (OnOffTableViewCell *) loadOnOffTableCell {
	OnOffTableViewCell *onOffCell;
	NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"OnOffTableViewCell" owner:self options:nil];	
	for(id currentNibObj in nib) {
		if ([currentNibObj isKindOfClass:[OnOffTableViewCell class]]) {
			onOffCell = (OnOffTableViewCell*) currentNibObj;
			break;
		}				
	}
	return onOffCell;
}

/*
 * Loads an DimmerTableCell from a nib-file.
 */
- (DimmerTableViewCell *) loadDimmerTableCell {
	DimmerTableViewCell *dimmerCell;
	NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"DimmerTableViewCell" owner:self options:nil];	
	for(id currentNibObj in nib) {
		if ([currentNibObj isKindOfClass:[DimmerTableViewCell class]]) {
			dimmerCell = (DimmerTableViewCell*) currentNibObj;
			break;
		}				
	}
	return dimmerCell;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	static NSString *sOnOffCellIdentifier = @"onoffcellidentifier";
	static NSString *sDimmerCellIdentifier = @"dimmercellidentifier";
	UITableViewCell *retVal = NULL;
	
	switch (indexPath.section) {
		case BUTTON_GROUP_ONOFF:
		{
			Alias *alias = [mOnOffAliasArray objectAtIndex:indexPath.row];
			//NSLog(@"Found on/off switch at row %d with alias %@", indexPath.row, alias.mAlias);
			//find cell to reuse:
			OnOffTableViewCell *onOffCell = (OnOffTableViewCell*) [tableView dequeueReusableCellWithIdentifier:sOnOffCellIdentifier];
			
			//load a new cell if no reusable one was found:
			if (onOffCell == NULL) {
				onOffCell = [self loadOnOffTableCell];			
			}
			
			//populate the cell:		
			if (onOffCell != NULL) { 
				onOffCell.mOnOffLabel.text = alias.mAlias;
			}
			retVal = onOffCell;
		}
			break;
		case BUTTON_GROUP_GROUPS:	
		{	
			Group *group = [mGroupAliasArray objectAtIndex:indexPath.row];
			NSLog(@"Found group switch at row %d in group %d with alias %@", indexPath.row, indexPath.section,group.mAlias);
			
			//find cell to reuse:
			OnOffTableViewCell *groupCell = (OnOffTableViewCell*) [tableView dequeueReusableCellWithIdentifier:sOnOffCellIdentifier];
			
			//load a new cell if no reusable one was found:
			if (groupCell == NULL) {
				groupCell = [self loadOnOffTableCell];			
			}
			
			//populate the cell:		
			if (groupCell != NULL) { 
				groupCell.mOnOffLabel.text = group.mAlias;
			}
			retVal = groupCell;
		}
			break;
		case BUTTON_GROUP_DIMMERS: 
		{
			Alias *alias = [mDimmerAliasArray objectAtIndex:indexPath.row];
			NSLog(@"Found dimmer switch at row %d with alias %@", indexPath.row, alias.mAlias);
			
			//find cell to reuse:
			DimmerTableViewCell *dimmerCell = (DimmerTableViewCell*) [tableView dequeueReusableCellWithIdentifier:sDimmerCellIdentifier];
			
			//load a new cell if no reusable one was found:
			if (dimmerCell == NULL) {
				dimmerCell = [self loadDimmerTableCell];			
			}
			
			//populate the cell:
			if (dimmerCell != NULL) { 
				NSString* dimmerLabel = alias.mAlias;
				dimmerCell.mDimmerLabel.text = dimmerLabel;		
			}
			
			retVal = dimmerCell;			
		}
			break;
			
		default:
			NSLog(@"Error - tried to access non-existant group!");
			break;
	}	
	
	
	return retVal;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
	CGFloat retVal = 0.0;
	
	switch (indexPath.section) {
		case BUTTON_GROUP_ONOFF:
			retVal = 100.0f;
			break;
		case BUTTON_GROUP_GROUPS:
			retVal = 100.0f;
			break;
		case BUTTON_GROUP_DIMMERS:
			retVal = 100.0f;
			break;
			
		default:
			NSLog(@"Error - tried to access non-existant group!");
			retVal = 0;
			break;
	}
	return retVal;
}

/*
 * A method that implements a workaround for the double "onSliderRelased"-event bug found in the iOS.
 * Basically it checks how long ago it was that we got the last event.
 *
 * @return 
 *		TRUE if the event is valid and should be handled, otherwise FALSE.
 */
- (BOOL) isEventValid {
	BOOL retVal = FALSE;
	NSDate *now = [NSDate date];
	double nowDouble = [now timeIntervalSince1970];
	double difference = nowDouble - self.latestTimeMark;
	self.latestTimeMark = nowDouble;
	if(difference<0.1f) {
		retVal = FALSE;
	} else {
		retVal = TRUE;
	}
	return retVal;
}

- (IBAction) onOnOffSliderValueChanged:(id) source {
	//NSLog(@"onOnOffSliderValueChanged");
}

- (IBAction) onOnOffSliderReleased:(id) source {
	
	AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	
	if([self isEventValid]) {		
		UISlider* slider = (UISlider*) source;
		
		UITableViewCell *cell = (UITableViewCell*) [[slider superview] superview];
		NSIndexPath* indexPath = [mTableView indexPathForCell:cell];
		
		NSLog(@"Retrieving object at (section, row) = (%d, %d)", indexPath.section, indexPath.row);
		NSString *aliasName = NULL;
		if (indexPath.section == BUTTON_GROUP_ONOFF) {
			aliasName = ((Alias*) [mOnOffAliasArray objectAtIndex:indexPath.row]).mAlias;
		} else if (indexPath.section == BUTTON_GROUP_GROUPS) {
			aliasName = ((Group*) [mGroupAliasArray objectAtIndex:indexPath.row]).mAlias;
		}
		
		if (aliasName != NULL) {
			float sliderValue = slider.value;
			
			[slider setValue: 0.5f];
			if (sliderValue > 0.5f) {
				[self turnOn: aliasName];
			} else if (sliderValue < 0.5f) {
				[self turnOff: aliasName];
			}
			
		}
	}		
}

- (IBAction) onDimmerSliderValueChanged:(id) source {
	//NSLog(@"onDimmerSliderValueChanged");
	//maybe add code here later
}
- (IBAction) onDimmerSliderReleased:(id) source {
	
	AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
	
	if([self isEventValid]) {		
		UISlider* slider = (UISlider*) source;
		
		UITableViewCell *cell = (UITableViewCell*) [[slider superview] superview];
		NSIndexPath* indexPath = [mTableView indexPathForCell:cell];
		
		NSLog(@"Retrieving object at (section, row) = (%d, %d)", indexPath.section, indexPath.row);
		
		Alias *alias = [mDimmerAliasArray objectAtIndex:indexPath.row];
		
		if (alias != NULL) {
			float sliderValue = slider.value;			
			[slider setValue: 0.0f];
			// TODO - add dimmer call here, for now, just fire off regular event
			NSInteger dimValue = (NSInteger) (sliderValue * 100.0);
			[self dim:alias.mAlias value: dimValue];			
		}
	}		
}


- (IBAction) onDimmerOnOffSliderValueChanged:(id) source {

}

- (IBAction) onDimmerOnOffSliderReleased:(id) source {
	if([self isEventValid]) {		
		UISlider* slider = (UISlider*) source;
		
		UITableViewCell *cell = (UITableViewCell*) [[slider superview] superview];
		NSIndexPath* indexPath = [mTableView indexPathForCell:cell];
		
		NSLog(@"Retrieving object at (section, row) = (%d, %d)", indexPath.section, indexPath.row);
		
		Alias *alias = [mDimmerAliasArray objectAtIndex:indexPath.row];
		
		if (alias != NULL) {
			float sliderValue = slider.value;
			
			[slider setValue: 0.5f];
			if (sliderValue > 0.5f) {
				[self turnOn:alias.mAlias];
			} else if (sliderValue < 0.5f) {
				[self turnOff:alias.mAlias];
			}
			
		}
	}
}


/*
 // Implement loadView to create a view hierarchy programmatically, without using a nib.
 - (void)loadView {
 }
 */

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
	mNetworkRequest = NULL;

}

- (void) viewDidAppear:(BOOL)animated {
	[super viewDidAppear:(BOOL)animated];
	DovadoAppDelegate *appDelegate = (DovadoAppDelegate*)[[UIApplication sharedApplication] delegate];
	if (![appDelegate extendedFeatures]) {
		[DialogUtils showNotSupportedDialog];
	} else {
		if (mNetworkRequest == NULL) {
			mNetworkRequest = [[DovadosNetworkRequest alloc] initWithHost: appDelegate.mHostAddress :6435];
		} else {
			[mNetworkRequest setMHost:appDelegate.mHostAddress];
		}
		[mNetworkRequest setUserInformation:appDelegate.mUser :appDelegate.mPassword: self];
		
		//allocate the new:
		mGroupAliasArray = [[NSMutableArray alloc] init];
		mOnOffAliasArray = [[NSMutableArray alloc] init];
		mDimmerAliasArray = [[NSMutableArray alloc] init];	
		
		if (appDelegate.mAliasArray != NULL) {		
			for(id object in appDelegate.mAliasArray) {
				if ([object isKindOfClass:[Alias class]]) {
					Alias* currentAlias = (Alias*) object;
					if ([currentAlias.mProtocol isEqualToString: @"NEXADIMMER"]) {	
						[mDimmerAliasArray addObject:currentAlias];
						[mOnOffAliasArray addObject:currentAlias];
					} else {
						[mOnOffAliasArray addObject:currentAlias];
					}
				}			
			}		
		}
		
		if (appDelegate.mGroupsArray != NULL) {		
			for(id object in appDelegate.mGroupsArray) {
				if ([object isKindOfClass:[Group class]]) {
					Group* currentGroup = (Group*) object;				
					[mGroupAliasArray addObject:currentGroup];	
				}
			}
		}
		
		[mTableView reloadData];
	}
}


/*
 * Utility function for dismissing progress-alerts.
 */
- (void) dismissProgressAlert {
	[DialogUtils dismissAlert:mProgressAlert];
	mProgressAlert = NULL;
}

#pragma mark DovadoRequestListener

- (void) aliasRequestDone: (NSMutableArray*) aliasArray {
	DovadoAppDelegate *appDelegate = (DovadoAppDelegate*)[[UIApplication sharedApplication] delegate];
	if (aliasArray != NULL) {
		
		//release the old!
		if (mOnOffAliasArray != NULL) {
			[mOnOffAliasArray release];		
		}
		
		if (mDimmerAliasArray != NULL) {
			[mDimmerAliasArray release];
		}
		
		//allocate the new:
		mOnOffAliasArray = [[NSMutableArray alloc] init];
		mDimmerAliasArray = [[NSMutableArray alloc] init];		
		
		
		for(id object in aliasArray) {
			if ([object isKindOfClass:[Alias class]]) {
				Alias* currentAlias = (Alias*) object;
				if ([currentAlias.mProtocol isEqualToString: @"NEXADIMMER"]) {	
					[mDimmerAliasArray addObject:currentAlias];
					[mOnOffAliasArray addObject:currentAlias];
				} else {
					[mOnOffAliasArray addObject:currentAlias];
				}
			}			
		}
		appDelegate.mAliasArray = mOnOffAliasArray;
	}
	
	[mTableView reloadData];
	[self dismissProgressAlert];
}

- (void) onoffRequestDone {
	[self dismissProgressAlert];
}


- (void) dovadoRequestFailed: (request_listener_error_t) error_code: (NSString*) message {
	NSLog(@"dovadoRequestFailed error_code: %i message: %@", error_code, message);
	[self dismissProgressAlert];
	if(error_code == ERROR_UNKNOWN_ERROR) {
		UIAlertView *errorAlert = [[UIAlertView alloc]
								   initWithTitle: NSLocalizedString(@"on_result_exception_dialog_title", @"Network Error")
								   message: NSLocalizedString(@"error_unknown_error", @"Unknown error")
								   delegate:self
								   cancelButtonTitle:NSLocalizedString(@"no_button_text", @"No")
								   otherButtonTitles:NSLocalizedString(@"yes_button_text", @"Yes"), nil];
		((UILabel*)[[errorAlert subviews] objectAtIndex:1]).textAlignment = UITextAlignmentLeft;
		[errorAlert show];
		[errorAlert release];
	} else {
		[DialogUtils showOnConnectionResultErrorDialog:error_code];
	}
}

- (void) dimRequestDone {
	[self dismissProgressAlert];	
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

- (void) groupsAndAliasRequestDone: (NSMutableArray*) groupsArray: (NSMutableArray*) aliasArray{
	DovadoAppDelegate *appDelegate = (DovadoAppDelegate*)[[UIApplication sharedApplication] delegate];
	//release the old!
	if (mGroupAliasArray != NULL) {
		[mGroupAliasArray release];
	}
	
	if (mOnOffAliasArray != NULL) {
		[mOnOffAliasArray release];		
	}
	
	if (mDimmerAliasArray != NULL) {
		[mDimmerAliasArray release];
	}
	
	//allocate the new:
	mGroupAliasArray = [[NSMutableArray alloc] init];
	mOnOffAliasArray = [[NSMutableArray alloc] init];
	mDimmerAliasArray = [[NSMutableArray alloc] init];	
	
	if (aliasArray != NULL) {		
		for(id object in aliasArray) {
			if ([object isKindOfClass:[Alias class]]) {
				Alias* currentAlias = (Alias*) object;
				if ([currentAlias.mProtocol isEqualToString: @"NEXADIMMER"]) {	
					[mDimmerAliasArray addObject:currentAlias];
					[mOnOffAliasArray addObject:currentAlias];
				} else {
					[mOnOffAliasArray addObject:currentAlias];
				}
			}			
		}
		appDelegate.mAliasArray = mOnOffAliasArray;
	}
	
	if (groupsArray != NULL) {		
		for(id object in groupsArray) {
			if ([object isKindOfClass:[Group class]]) {
				Group* currentGroup = (Group*) object;				
				[mGroupAliasArray addObject:currentGroup];	
			}
		}
		appDelegate.mGroupsArray = mGroupAliasArray;
	}
	
	[mTableView reloadData];
	[self dismissProgressAlert];
}

- (void)viewDidUnload {
	if (mGroupAliasArray != NULL) {
		[mGroupAliasArray release];
	}
	
	if (mOnOffAliasArray != NULL) {
		[mOnOffAliasArray release];		
	}
	
	if (mDimmerAliasArray != NULL) {
		[mDimmerAliasArray release];
	}
	
	mGroupAliasArray = NULL;
	mOnOffAliasArray = NULL;
	mDimmerAliasArray = NULL;
	
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
	[mNetworkRequest release];
    [super dealloc];
}


@end
